package com.lzh.mybatisdemo.handler;

import com.lzh.mybatisdemo.enums.BaseEnum;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @Description: Integer/String 转 enum
 * @Author: LiuZiHao
 * @Date: 2022/4/27 17:01
 */
@MappedTypes(value = BaseEnum.class)
@MappedJdbcTypes(value = {JdbcType.VARCHAR, JdbcType.INTEGER})
public class EnumTypeHandler<T extends BaseEnum> extends BaseTypeHandler<T> {

    private Class<T> type;

    public EnumTypeHandler(Class<T> type) {
        if (type == null) {
            throw new IllegalArgumentException("Type argument cannot be null");
        }
        this.type = type;
    }

    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, T baseEnum, JdbcType jdbcType) throws SQLException {
        if (baseEnum.getValue() instanceof Integer) {
            preparedStatement.setInt(i, (Integer) baseEnum.getValue());
        } else if (baseEnum.getValue() instanceof String) {
            preparedStatement.setString(i, (String) baseEnum.getValue());
        }
    }

    @Override
    public T getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
        return convert(resultSet.getObject(columnName));
    }

    @Override
    public T getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
        return convert(resultSet.getObject(columnIndex));
    }

    @Override
    public T getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
        return convert(callableStatement.getObject(columnIndex));
    }

    //数字/字符串 转枚举
    private T convert(Object value) {
        if (null == value) {
            return null;
        }
        T[] enums = type.getEnumConstants();
        if (enums == null) {
            throw new IllegalArgumentException(type.getSimpleName() + " does not represent an enum type.");
        }
        for (T em : enums) {
            if (value instanceof Boolean) {
                if ((Boolean) value) {
                    if (em.getValue().toString().equals("1")) {
                        return em;
                    }
                } else {
                    if (em.getValue().toString().equals("0")) {
                        return em;
                    }
                }
            } else {
                if (em.getValue().toString().equals(value.toString())) {
                    return em;
                }
            }
        }
        return null;
    }
}
